home *** CD-ROM | disk | FTP | other *** search
- /* M16MCH:C */
-
- /*
- * (C) Copyright 1991
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
- #include <stdio.h>
- #include <setjmp.h>
- #include "asm.h"
- #include "m6816.h"
-
- #define NB 256
-
- int *bp;
- int bm;
- int bb[NB];
-
- /*
- * Process a machine op.
- */
- VOID
- machine(mp)
- struct mne *mp;
- {
- register op, rf, cpg;
- struct expr e1, e2, e3;
- char id[NCPS];
- struct area *espa;
- int c, pc, t1, t2, vn;
-
- pc = dot.s_addr;
- cpg = 0;
- op = mp->m_valu;
- switch (rf = mp->m_type) {
-
- case S_SDP:
- e1.e_mode = 0;
- e1.e_flag = 0;
- e1.e_addr = 0;
- e1.e_base.e_ap = NULL;
- espa = NULL;
- if (more()) {
- expr(&e1, 0);
- if (e1.e_flag == 0 && e1.e_base.e_ap == NULL) {
- if (e1.e_addr) {
- err('b');
- }
- }
- if ((c = getnb()) == ',') {
- getid(id, -1);
- espa = alookup(id);
- if (espa == NULL) {
- err('u');
- }
- } else {
- unget(c);
- }
- }
- if (espa) {
- outdp(espa, &e1);
- } else {
- outdp(dot.s_area, &e1);
- }
- lmode = SLIST;
- break;
-
- case S_IMMA:
- if (addr(&e1) == T_IMM) {
- if (mchimm(&e1)) {
- outab(PAGE3);
- outab(op);
- outrw(&e1, R_NORM);
- } else {
- outab(op);
- outrb(&e1, R_NORM);
- }
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_IM16:
- if (addr(&e1) == T_IMM) {
- outab(PAGE3);
- outab(op);
- outrw(&e1, R_NORM);
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_BIT:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- if ((t2 != T_IMM) && (t2 != T_EXT)) {
- aerr();
- }
- if (t1 == T_EXT) {
- outab(op|0x30);
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- outrw(&e1, R_NORM);
- } else
- if (t1 & T_INDX) {
- if (mchindx(t1, &e1)) {
- outab(op|(t1 & 0x30));
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- outrw(&e1, R_NORM);
- } else {
- outab(PAGE1);
- outab(op|(t1 & 0x30));
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- }
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_BITW:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- if ((t2 != T_IMM) && (t2 != T_EXT)) {
- aerr();
- }
- if (t1 == T_EXT) {
- t1 |= 0x30;
- } else
- if (t1 & T_INDX) {
- if (t1 & T_IND8) {
- aerr();
- }
- } else {
- aerr();
- }
- outab(PAGE2);
- outab(op|(t1 & 0x30));
- outrw(&e2, R_NORM);
- outrw(&e1, R_NORM);
- break;
-
- case S_BRBT:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- comma();
- addr(&e3);
- if ((t2 != T_IMM) && (t2 != T_EXT)) {
- aerr();
- }
- if (t1 == T_EXT) {
- outab(op|0x30);
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- outrw(&e1, R_NORM);
- if (mchabs(&e3)) {
- vn = e3.e_addr - dot.s_addr - 2;
- outaw(vn);
- } else {
- outrw(&e3, R_PCR);
- }
- } else
- if (t1 & T_INDX) {
- if ((t1 & T_IND8) || (t1 & T_IND16)) {
- ;
- } else
- if (mchindx(t1, &e1)) {
- t1 |= T_IND16;
- } else {
- if (mchabs(&e3)) {
- vn = e3.e_addr - dot.s_addr - 4;
- if ((vn < -128) || (vn > 127)) {
- t1 |= T_IND16;
- } else {
- t1 |= T_IND8;
- }
- } else {
- t1 |= T_IND16;
- }
- }
- if (t1 & T_IND8) {
- if (op == 0x0A)
- op = 0xCB;
- if (op == 0x0B)
- op = 0x8B;
- outab(op|(t1 & 0x30));
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- if (mchabs(&e3)) {
- vn = e3.e_addr - dot.s_addr - 1;
- if ((vn < -128) || (vn > 127))
- aerr();
- outab(vn);
- } else {
- outrb(&e3, R_PCR);
- }
- } else
- if (t1 & T_IND16) {
- outab(op|(t1 & 0x30));
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- outrw(&e1, R_NORM);
- if (mchabs(&e3)) {
- vn = e3.e_addr - dot.s_addr - 2;
- outaw(vn);
- } else {
- outrw(&e3, R_PCR);
- }
- }
- } else {
- dot.s_addr += 6;
- aerr();
- }
- break;
-
- case S_LDED:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- outab(PAGE2);
- outab(op);
- outrw(&e1, R_NORM);
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_MAC:
- t1 = addr(&e1);
- if (more()) {
- comma();
- t2 = addr(&e2);
- if ((t1 != T_IMM) || !mchabs(&e1) ||
- (t2 != T_IMM) || !mchabs(&e2))
- aerr();
- outab(op);
- outab(((e1.e_addr << 4) & 0xF0) | (e2.e_addr & 0x0F));
- } else {
- if (t1 != T_IMM)
- aerr();
- outab(op);
- outrb(&e1, R_NORM);
- }
- break;
-
- case S_PSHM:
- vn = 0;
- do {
- if ((t1 = admode(pshm)) == 0 || vn & t1)
- aerr();
- vn |= t1;
- } while (more() && comma());
- outab(op);
- outab(vn);
- break;
-
- case S_PULM:
- vn = 0;
- do {
- if ((t1 = admode(pulm)) == 0 || vn & t1)
- aerr();
- vn |= t1;
- } while (more() && comma());
- outab(op);
- outab(vn);
- break;
-
- case S_JXX:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- if ((t1 != T_IMM) && (t1 != T_EXT)) {
- aerr();
- }
- if (t2 == T_EXT) {
- if (op == 0x4B)
- outab(0x70);
- if (op == 0x89)
- outab(0xFA);
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- outrw(&e2, R_NORM);
- } else
- if ((t2 & T_INDX) && (t2 != (T_INDX|T_IND8))) {
- outab(op|(t2 & 0x30));
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- outrw(&e2, R_NORM);
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_MOVB:
- case S_MOVW:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- if((t1 == T_EXT) && (t2 == T_EXT)) {
- outab(PAGE3);
- outab(op|0xFE);
- outrw(&e1, R_NORM);
- outrw(&e2, R_NORM);
- } else
- if((t1 & T_INDX) && (t2 == T_EXT)) {
- outab(op|(t1 & 0x30));
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- outrw(&e2, R_NORM);
- } else
- if((t1 == T_EXT) && (t2 & T_INDX)) {
- outab(op|0x02|(t2 & 0x30));
- mchubyt(&e2);
- outrb(&e2, R_USGN);
- outrw(&e1, R_NORM);
- } else {
- dot.s_addr += 6;
- aerr();
- }
- break;
-
- case S_CMP:
- case S_LOAD:
- case S_STOR:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- outab(PAGE1);
- outab(op|0x30);
- outrw(&e1, R_NORM);
- } else
- if ((t1 == T_IMM) && (rf != S_STOR)) {
- outab(PAGE3);
- if (rf == S_CMP)
- outab(op|0x30);
- if (rf == S_LOAD)
- outab((op|0x30) & 0xBF);
- outrw(&e1, R_NORM);
- } else
- if (t1 & T_INDX) {
- if (mchindx(t1, &e1)) {
- outab(PAGE1);
- outab(op|(t1 & 0x30));
- outrw(&e1, R_NORM);
- } else {
- outab(op|(t1 & 0x30));
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- }
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_SOPW:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- t1 |= 0x30;
- } else
- if (t1 & T_INDX) {
- if (t1 & T_IND8) {
- aerr();
- }
- } else {
- aerr();
- }
- outab(PAGE2);
- outab(op|(t1 & 0x30));
- outrw(&e1, R_NORM);
- break;
-
- case S_SOP:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- outab(PAGE1);
- outab(op|0x30);
- outrw(&e1, R_NORM);
- } else
- if (t1 & T_INDX) {
- if (mchindx(t1, &e1)) {
- outab(PAGE1);
- outab(op|(t1 & 0x30));
- outrw(&e1, R_NORM);
- } else {
- outab(op|(t1 & 0x30));
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- }
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_DOPE:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- outab(PAGE3);
- outab(op|0x30);
- outrw(&e1, R_NORM);
- } else
- if (t1 == T_IMM) {
- if (op == 0x41) {
- if (mchimm(&e1)) {
- outab(PAGE3);
- outab((op|0x30)&0x3F);
- outrw(&e1, R_NORM);
- } else {
- outab(0x7C);
- outrb(&e1, R_NORM);
- }
- } else {
- outab(PAGE3);
- outab((op|0x30)&0x3F);
- outrw(&e1, R_NORM);
- }
- } else
- if ((t1 & T_INDX) && (t1 != (T_INDX|T_IND8))) {
- outab(PAGE3);
- outab(op|(t1 & 0x30));
- outrw(&e1, R_NORM);
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_DOPD:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- outab(PAGE3);
- outab(op|0x70);
- outrw(&e1, R_NORM);
- } else
- if ((t1 == T_IMM) && (op != 0x8A)) {
- if (op == 0x81) {
- if (mchimm(&e1)) {
- outab(PAGE3);
- outab(op|0x30);
- outrw(&e1, R_NORM);
- } else {
- outab(0xFC);
- outrb(&e1, R_NORM);
- }
- } else {
- outab(PAGE3);
- outab(op|0x30);
- outrw(&e1, R_NORM);
- }
- } else
- if (t1 & T_INDX) {
- if (mchindx(t1, &e1)) {
- outab(PAGE3);
- outab(op|0x40|(t1 & 0x30));
- outrw(&e1, R_NORM);
- } else {
- outab(op|(t1 & 0x30));
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- }
- } else
- if (t1 & T_E_I) {
- outab(PAGE2);
- outab(op|(t1 & 0x30));
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_DOP:
- t1 = addr(&e1);
- if (t1 == T_EXT) {
- outab(PAGE1);
- outab(op|0x30);
- outrw(&e1, R_NORM);
- } else
- if ((t1 == T_IMM) && (op != 0x4A) && (op != 0xCA)) {
- outab(op|0x30);
- outrb(&e1, R_NORM);
- } else
- if (t1 & T_INDX) {
- if (mchindx(t1, &e1)) {
- outab(PAGE1);
- outab(op|(t1 & 0x30));
- outrw(&e1, R_NORM);
- } else {
- outab(op|(t1 & 0x30));
- mchubyt(&e1);
- outrb(&e1, R_USGN);
- }
- } else
- if (t1 & T_E_I) {
- outab(PAGE2);
- outab(op|(t1 & 0x30));
- } else {
- dot.s_addr += 4;
- aerr();
- }
- break;
-
- case S_INH37:
- cpg += PAGE3-PAGE2;
-
- case S_INH27:
- cpg += PAGE2;
- outab(cpg);
- outab(op);
- break;
-
- case S_LBRA:
- cpg += PAGE3-PAGE2;
-
- case S_LBSR:
- cpg += PAGE2;
- expr(&e1, 0);
- outab(cpg);
- outab(op);
- if (mchabs(&e1)) {
- vn = e1.e_addr - dot.s_addr - 2;
- outaw(vn);
- } else {
- outrw(&e1, R_PCR);
- }
- if (e1.e_mode != S_USER)
- aerr();
- break;
-
- case S_BRA:
- case S_BSR:
- expr(&e1, 0);
- outab(op);
- if (mchabs(&e1)) {
- vn = e1.e_addr - dot.s_addr - 1;
- if ((vn < -128) || (vn > 127))
- rerr();
- outab(vn);
- } else {
- outrb(&e1, R_PCR);
- }
- if (e1.e_mode != S_USER)
- rerr();
- break;
-
- default:
- err('o');
- }
- if (pc & 0x0001) {
- err('b');
- dot.s_addr += 1;
- }
- }
-
- /*
- * Check if argument is absolute
- */
- int
- mchabs(e1)
- struct expr *e1;
- {
- if (e1->e_base.e_ap == NULL || e1->e_base.e_ap == dot.s_area) {
- return(-1);
- }
- return(0);
- }
-
- /*
- * Addressing error if argument is absolute
- * and unsigned byte is greater than 0x00FF
- */
- VOID
- mchubyt(e1)
- struct expr *e1;
- {
- if (mchabs(e1) && (e1->e_addr & 0xFF00)) {
- aerr();
- }
- }
-
- /*
- * Check index mode
- */
- int
- mchindx(t1,e1)
- int t1;
- struct expr *e1;
- {
- int flag;
-
- if (t1 & T_IND8) {
- flag = 0;
- } else
- if (t1 & T_IND16) {
- flag = 1;
- } else
- if (pass == 0) {
- flag = 1;
- } else
- if (pass == 1) {
- if (e1->e_addr >= dot.s_addr)
- e1->e_addr -= fuzz;
- flag = 0;
- if (e1->e_addr>255 || e1->e_flag || e1->e_base.e_ap)
- flag = 1;
- if (setbit(flag))
- flag = 1;
- } else {
- if (getbit()) {
- flag = 1;
- } else {
- flag = 0;
- }
- }
- return(flag);
- }
-
- /*
- * Check immediate mode
- */
- int
- mchimm(e1)
- struct expr *e1;
- {
- int flag, vn;
-
- if (pass == 0) {
- flag = 1;
- } else
- if (pass == 1) {
- if (e1->e_addr >= dot.s_addr)
- e1->e_addr -= fuzz;
- vn = e1->e_addr;
- flag = 0;
- if ((vn<-128) || (vn>127) || e1->e_flag || e1->e_base.e_ap)
- flag = 1;
- if (setbit(flag)) {
- flag = 1;
- }
- } else {
- if (getbit()) {
- flag = 1;
- } else {
- flag = 0;
- }
- }
- return(flag);
- }
-
- /*
- * Machine specific initialization.
- * Set up the bit table.
- */
- VOID
- minit()
- {
- bp = bb;
- bm = 1;
- }
-
- /*
- * Store `b' in the next slot of the bit table.
- * If no room, force the longer form of the offset.
- */
- int
- setbit(b)
- {
- if (bp >= &bb[NB])
- return(1);
- if (b)
- *bp |= bm;
- bm <<= 1;
- if (bm == 0) {
- bm = 1;
- ++bp;
- }
- return(b);
- }
-
- /*
- * Get the next bit from the bit table.
- * If none left, return a `1'.
- * This will force the longer form of the offset.
- */
- int
- getbit()
- {
- register f;
-
- if (bp >= &bb[NB])
- return (1);
- f = *bp & bm;
- bm <<= 1;
- if (bm == 0) {
- bm = 1;
- ++bp;
- }
- return (f);
- }
-
- /*
- * The next character must be a
- * comma.
- */
- int
- comma()
- {
- if (getnb() != ',')
- qerr();
- return(1);
- }
-